home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hack-Mag 7
/
Hack-Mag - Issue 7 (1991-11-27)(D-Tect)(PD).adf
/
Sources
/
PointInPolygonProblem.s
< prev
Wrap
Text File
|
1991-11-25
|
10KB
|
413 lines
*****************************************************************************
*** Point in Polygon Routine (c) November 1991 by McDeal/D-TECT ***
*** Released in HACK-MAG Issue #7 ***
*****************************************************************************
;With this routine you can test whether a point is within a convex polygon
;or not.
;This formula was used: C = (x2-x1)*(y-y1)-(y2-y1)*(x-x1)
;when C<0, then the point P(x,y) is left of the line (x1,y1,x2,y2)
;when C>0, then the point P(x,y) is right of the line (x1,y1,x2,y2)
;The result of this formula is only correct if your coordinate origin is
;in the upper left corner of the screen. If it is in the lower left corner
;you have to interprete the result the other way round...
;IMPORTANT NOTE: I didn't optimize anything of this example because I was
;in a BIG hurry! And I think it is much easier for beginners to understand
;source codes which aren't optimized... You know...
; signed: McDeal/D-TECT
;PS: GREEN means: Inside polygon.
; RED means: Outside polygon. Now start it!
;PPS: This is a Devpac Source Code!
***************************************************
*** Constants Definition ***
***************************************************
PlaneWidth = 40
PlaneLen = PlaneWidth*256
SpriteHigh = 1
SpriteWidth = 16
MouseClipX = 320-SpriteWidth+1
MouseClipY = 256-SpriteHigh-5
DL_MInterns = $ca
SML = 0
***************************************************
*** Program Start ***
***************************************************
opt o+
section a,code_c
Start: lea $dff000,a5
bsr DrawPolygon
bsr.s InitInts
bsr.s InitSprite
bsr.s SetPlanePtr
bsr StartCopper
bsr Main
bsr StopCopper
bsr.s ReInitInts
moveq #0,d0
rts
***************************************************
*** Init Interrupt ***
***************************************************
InitInts: move.w $1c(a5),d0 ;Save INTENA
bset #15,d0
move.w d0,Interrupts
move.w #$3fff,$9a(a5) ;turn off all Ints (INTENA)
move.l $6c.w,Level3Int ;Save old Level 3 Int
lea MouseRoutine(pc),a0 ;Set New Routine Ptr
move.l a0,$6c.w
move.w #$c020,$9a(a5) ;Permit Level 3 Int
rts
Interrupts: dc.w 0
Level3Int: dc.l 0
***************************************************
*** ReInit Interrupts ***
***************************************************
ReInitInts: move.w #$3fff,$9a(a5) ;turn off all Ints (INTENA)
move.l Level3Int(pc),$6c.w ;set old Level3Int Ptr
move.w Interrupts(pc),$9a(a5) ;set old INTENA contents
rts
***************************************************
*** Init Sprite ***
***************************************************
InitSprite: move.l #MouseSpr,d0 ;Sprite Structure Ptr
lea MouseSprite(pc),a0 ;NCList Ptr
move.w d0,6(a0) ;Set Ptr
swap d0
move.w d0,2(a0)
rts
***************************************************
*** Set Plane Ptr in Copperlist ***
***************************************************
SetPlanePtr: lea PlanePtr(pc),a1
move.l #Plane,d0
move.w d0,6(a1) ;Low Word
swap d0
move.w d0,2(a1) ;High Word
rts
***************************************************
*** Start/Stop Copper ***
***************************************************
StartCopper: move.w #$0380,$96(a5)
move.l #NCList,$84(a5)
clr.w $8a(a5)
move.w #$83a0,$96(a5)
clr.w $36(a5) ;Clear JOY0DAT
rts
StopCopper: move.w #$0380,$96(a5)
clr.w $88(a5)
move.w #$8380,$96(a5)
rts
***************************************************
*** Draw Polygon ***
***************************************************
DrawPolygon: lea $dff002,a6
lea Koords(pc),a2
move.w (a2)+,d7 ;Number of Lines
.DrawLineLoop: lea Plane,a0
moveq #PlaneWidth,d4 ;This shitty loop isn't
moveq #-1,d5 ;optimized!!! Don't blame me!
movem.w (a2)+,d0-d3
.WB: btst #6,(a6)
bne.s .WB
move.w d5,$44-$02(a6)
move.w d5,$72-$02(a6)
move.w #$8000,$74-$02(a6)
move.w d4,$60-$02(a6)
move.w d4,$66-$02(a6)
bsr.s DrawLine
dbf d7,.DrawLineLoop
rts
***************************************************
*** DrawLine ***
***************************************************
;Needs:
; a0 PlanePtr
; a6 $dff002
; d0/d1 x,y start pos
; d2/d3 x,y end pos
; d4 Width of plane
;Kills:
; d0-d4/a0-a1 (+d5 in Fill Mode)
DrawLine: cmp.w d1,d3 ;drawing only from top to bottom is
bge.s .y1ly2 ;necessary for:
exg d0,d2 ;a: up-down differences (same koords)
exg d1,d3 ;b: blitter invert bit (only at top of line)
.y1ly2: sub.w d1,d3 ;d3:yd
;here we could do an optimization with special shifts
;depending on the PlaneWidth value ... i know it, but please, let it be.
mulu d4,d1 ;use muls for neg y-vals
add.l d1,a0 ;please don't use add.w here!
moveq #0,d1 ;d1:quant-counter
sub.w d0,d2 ;d2:xd
bge.s .xdpos
addq.w #2,d1 ;set bit 1 of quant-counter (here it could be a moveq)
neg.w d2
.xdpos: moveq #$f,d4 ;d4 full cleaned (for later oktants move.b)
and.w d0,d4
lsr.w #3,d0 ;yeah, on byte (necessary for bchg) ....
add.w d0,a0 ;... blitter ands automagically
ror.w #4,d4 ;4:shift
or.w #$b00+DL_MInterns,d4 ;bltcon0-codes
swap d4
cmp.w d2,d3 ;which delta is the biggest?
bge.s .dygdx
addq.w #1,d1 ;set bit 0 of quant-counter
exg d2,d3 ;exchange xd with yd
.dygdx: add.w d2,d2 ;d2:xd*2
move.w d2,d0 ;d0:save for $52(a6)
sub.w d3,d0 ;d0:xd*2-yd
addx.w d1,d1 ;Bit0:sign-bit
move.b .oktants(pc,d1.w),d4 ;in low byte of d4 (upper byte cleaned above)
swap d2
move.w d0,d2
sub.w d3,d2 ;d2:2*(xd-yd)
moveq #6,d1 ;d1:shiftval(not necessary) + testval for the blitter
lsl.w d1,d3 ;d3:BLTSIZE
add.w #$42,d3
lea $52-2(a6),a1 ;a1:CUSTOM + $52
;WARNING: if you use fastmem and an extreme DMA-Access (e.g. 6
;planes and copper), you should insert a tst.b (a6) here (for the
;shitty AGNUS-BUG).
.WB: btst d1,(a6) ;waiting for the blitter ...
bne.s .WB
move.l d4,$40-2(a6) ;writing to the blitter regs as fast as possible.
move.l d2,$62-2(a6)
move.l a0,$48-2(a6)
move.w d0,(a1)+
move.l a0,(a1)+ ;shit-word buffer pt.
move.w d3,(a1)
rts
; ------------- oktant-table --------------------------------------------
.Oktants: dc.b SML+1,SML+1+$40
dc.b SML+17,SML+17+$40
dc.b SML+9,SML+9+$40
dc.b SML+21,SML+21+$40
***************************************************
*** Main Loop ***
***************************************************
Main: move.l $04(a5),d0
and.l #$1ff00,d0
cmp.l #150*256,d0
bne.s Main
.Wait: move.l $04(a5),d0
and.l #$1ff00,d0
cmp.l #151*256,d0
bne.s .Wait
bsr.s TestMousePos ;This is the MAIN routine!
btst #6,$bfe001
bne.s Main
.WB: btst #6,2(a5)
bne.s .WB
rts
***************************************************
*** Test Mouse Pos ***
***************************************************
TestMousePos: lea Koords(pc),a0 ;Polygon Ptr
movem.w MousePos(pc),d4-d5 ;X,Y Coord of Point
bsr.s PointInPolygon
tst.w d0 ;Test Flag
beq.s .InPolygon ;if d0 = 0 -> inside!
.Beep: move.w #$f00,$dff180 ;Point outside polygon
rts
.InPolygon: move.w #$0f0,$dff180 ;Point inside polygon
.Exit: rts
***************************************************
*** Point in Polygon Routine ***
***************************************************
;a0 = Ptr on Polygon Coordinate Lis (Polygon Clockwise!)
;d4 = X-Coord of point
;d5 = Y-Coord of point
;-> d0 <> 0 when point outside; d0 = 0 when point inside
PointInPolygon: move.w (a0)+,d7 ;Amount of polygon lines-1
.PolygonLoop: movem.w (a0)+,d0-d3 ;Get Line Coords
sub.w d0,d2 ;(x2-x1)
move.w d5,d6 ;save y
sub.w d1,d6 ;(y-y1)
muls d6,d2 ;(y-y1)*(x2-x1)
sub.w d1,d3 ;(y2-y1)
move.w d4,d6 ;save x
sub.w d0,d6 ;(x-x1)
muls d6,d3 ;(y2-y1)*(x-x1)
sub.l d3,d2 ;(y-y1)*(x2-x1)-(y2-y1)*(x-x1)
bmi.s .OutOfPolygon ;if neg-> outside
dbf d7,.PolygonLoop
moveq #0,d0 ;set inside-flag
rts
.OutOfPolygon: moveq #-1,d0 ;set outside-flag
rts
*** Polygon Structure ***
Koords: dc.w 5-1 ;Polygon with 5 lines
dc.w 55,1,100,30 ;1. lines
dc.w 100,30,80,90 ;2. lines
dc.w 80,90,20,80 ;3. lines
dc.w 20,80,10,30 ;4. lines
dc.w 10,30,55,1 ;5. lines
***************************************************
*** Level3Int (Mouse-Routine) ***
***************************************************
MouseRoutine: movem.l d0-d4/a0/a5,-(sp)
lea $dff000,a5
btst #5,$1e+1(a5) ;VBI ? (INTREQR+1)
beq.s .Exit ;no-> Exit
move.w #$0020,$9c(a5) ;Clear VBI Bit
lea MousePos(pc),a0
move.w (a0)+,d0
move.w (a0)+,d1
move.w $0a(a5),d2
move.w d2,d3
sub.b 1(a0),d2
move.b d2,d4
ror.w #8,d2
sub.b (a0),d2
move.w d3,(a0)
ext.w d4
add.w d4,d0
bgt.s .Right
moveq #0,d0
bra.s .Up
.Right: cmp.w #MouseClipX,d0
blt.s .Up
move.w #MouseClipX,d0
.Up: ext.w d2
add.w d2,d1
bgt.s .Down
moveq #0,d1
bra.s .SetSpr
.Down: cmp.w #MouseClipY,d1
blt.s .SetSpr
move.w #MouseClipY,d1
;\
; >- Now set the Sprite
;/
.SetSpr: movem.w d0-d1,-(a0) ;Set X,Y
lea MouseSpr(pc),a0 ;Sprite Structure Ptr
add.w #128,d0
add.w #42,d1
move.w d1,d3
addq.w #SpriteHigh,d3
moveq #0,d4
lsl.w #8,d1
addx.b d4,d4
lsl.w #8,d3
addx.b d4,d4
or.w d4,d3
lsr.w #1,d0
addx.b d3,d3
or.w d0,d1
move.w d1,(a0)+
move.w d3,(a0)
.Exit: movem.l (sp)+,d0-d4/a0/a5
rte
MousePos: dc.w 0,0 ; Don't change the order!
OldMove: dc.w 0 ;/
***************************************************
*** Datas ***
***************************************************
NCList:
MouseSprite: dc.l $01200000,$01220000,$01240000,$01260000
dc.l $01280000,$012a0000,$012c0000,$012e0000
dc.l $01300000,$01320000,$01340000,$01360000
dc.l $01380000,$013a0000,$013c0000,$013e0000
dc.l $008e2981,$009029c1,$00920038,$009400d0
dc.l $01020000,$01040000,$01080000,$010a0000
dc.l $01000200,$01a20ff0
PlanePtr: dc.l $00e00000,$00e20000
dc.l $01001200
dc.l $01800000,$018200ff
dc.l -2
MouseSpr: dc.w 0,0
dc.w $8000,$0000
dc.w 0,0
***************************************************
*** BSS Data Segment ***
***************************************************
section b,bss_c
Plane: ds.b PlaneLen
END